using System;
using ChessKit.Common.Primitives;

namespace ChessKit.ChessLogics.Internals
{
  internal static class Piece
  {
    private static readonly CompactPiece[] Symbols;

    static Piece()
    {
      Symbols = new CompactPiece['z' - 'A'];

      Symbols['K' - 'A'] = CompactPiece.WhiteKing;
      Symbols['k' - 'A'] = CompactPiece.BlackKing;
      Symbols['Q' - 'A'] = CompactPiece.WhiteQueen;
      Symbols['q' - 'A'] = CompactPiece.BlackQueen;
      Symbols['R' - 'A'] = CompactPiece.WhiteRook;
      Symbols['r' - 'A'] = CompactPiece.BlackRook;
      Symbols['B' - 'A'] = CompactPiece.WhiteBishop;
      Symbols['b' - 'A'] = CompactPiece.BlackBishop;
      Symbols['N' - 'A'] = CompactPiece.WhiteKnight;
      Symbols['n' - 'A'] = CompactPiece.BlackKnight;
      Symbols['P' - 'A'] = CompactPiece.WhitePawn;
      Symbols['p' - 'A'] = CompactPiece.BlackPawn;
    }

    public static CompactPiece Parse(char symbol)
    {
      CompactPiece piece;
      try
      {
        piece = Symbols[symbol - 'A'];
      }
      catch (IndexOutOfRangeException)
      {
        throw new FormatException("illegal character");
      }
      if (piece == CompactPiece.EmptyCell)
        throw new FormatException("illegal character");
      return piece;
    }

    // TODO: Make consistent with Pt.TypeColorMap
    private static readonly IPiece[] Map = new[]
                                             {
                                               null,
                                               Pt.P, Pt.B, Pt.N, Pt.R, Pt.Q, Pt.K, null, null, 
                                               Pt.p, Pt.b, Pt.n, Pt.r, Pt.q, Pt.k,
                                             };

    public static CompactPiece Pack(IPiece value)
    {
      if (value == null) return CompactPiece.EmptyCell;
      return (CompactPiece)value.CompactValue;
    }
    public static IPiece Unpack(CompactPiece value)
    {
      return Map[(int)value];
    }
    public static CompactPiece Get(PieceType pieceType, PieceColor pieceColor)
    {
      var res = (CompactPiece) pieceType;
      if (pieceColor == PieceColor.Black)
        return res | CompactPiece.IsBlack;
      return res;
    }

    public static PieceColor Color(CompactPiece piece)
    {
      return (piece & CompactPiece.IsBlack) == 0 ? PieceColor.White : PieceColor.Black;
    }

    public static PieceType Type(CompactPiece piece)
    {
      return (PieceType) (piece & ~CompactPiece.IsBlack);
    }
	  public static PieceColor Invert(this PieceColor color)
	  {
		  return color == PieceColor.White ? PieceColor.Black : PieceColor.White;
	  }
  }
}